#pragma once

#include <iostream>
#include <vector>
#include <pthread.h>
#include <unistd.h>
#include "Sem.hpp"

using namespace SemModule;


static const int default_value = 10;

template <typename T>
class RingQueue
{
public:
    // 构造函数
    RingQueue(int cap = default_value)
        : _cap(cap),
          _rq(cap),

          _empty_sem(cap),
          _p_step(0),

          _full_sem(0),
          _c_step(0)
    {
    }

    // 入队操作
    void enqueue(const T &data)
    {
        // 生产者
        _empty_sem.P();
        _rq[_p_step] = data;
        _p_step = (_p_step + 1) % _cap;
        _full_sem.V();
    }

    // 出队操作
    void dequeue(T *out)
    {
        // 消费者
        _full_sem.P();
        *out = _rq[_c_step];
        _c_step = (_c_step + 1) % _cap;
        _empty_sem.V();
    }

    // 析构函数
    ~RingQueue()
    {
    }

private:
    std::vector<T> _rq; // 环形队列
    int _cap;           // 容量

    // 生产者
    Sem _empty_sem; // 空闲位置信号量
    int _p_step;    // 生产者指针

    // 消费者
    Sem _full_sem; // 满位置信号量
    int _c_step;   // 消费者指针
};